﻿/*
 * iec104app.hpp
 *
 *  Created on: 2017年2月4日
 *      Author: work
 */

#ifndef _DM_PROTOCOL_FRAME104APDU_HPP_
#define _DM_PROTOCOL_FRAME104APDU_HPP_

#include <dm/export.hpp>

#ifndef DM_API_PROTOCOL
#define DM_API_PROTOCOL DM_API_IMPORT
#endif

#include <dm/types.hpp>

namespace dm{
namespace protocol{

/**
 * APDU类
 */
class DM_API_PROTOCOL CFrame104Apdu{
	CFrame104Apdu( const CFrame104Apdu& );
public:
	enum{
		MaxLenOfElements = 256,

		MaxCountOfObjs_3_M_DP_NA_1 = 240/1,

		MaxCountOfObjs_11_M_ME_NB_1 = 240/3,

		MaxCountOfObjs_13_M_ME_NC_1 = 240/5,

		MaxCountOfObjs_15_M_IT_NA_1 = 240/6,

		MaxCountOfObjs_31_M_DP_TB_1 = 240/11,

		MaxCountOfObjs_35_M_ME_TE_1 = 240/13,

		MaxCountOfObjs_36_M_ME_TF_1 = 240/15,

		MaxCountOfObjs_37_M_IT_TB_1 = 240/15,
	};

	enum EType{
		FAType_Undefined	= 0x00,	// 未定义

		// 监视方向
		M_SP_NA_1	= 0x01,			// 单点信息
		M_DP_NA_1	= 0x03,			// 双点信息
		M_ST_NA_1	= 0x05,			// 步位置信息
		M_BO_NA_1	= 0x07,			// 32 比特串
		M_ME_NA_1	= 0x09,			// 测量值，规一化值
		M_ME_NB_1	= 0x0b,			// 测量值，标度化值
		M_ME_NC_1	= 0x0d,			// 测量值，短浮点数
		M_IT_NA_1	= 0x0f,			// 累计量
		M_PS_NA_1	= 0x14,			// 带状态检出的成组单点信息
		M_ME_ND_1	= 0x11,			// 不带品质描述的规一化测量值

		M_SP_TB_1	= 0x1e,			// 带时标CP56Time2a 的单点信息
		M_DP_TB_1	= 0x1f,			// 带时标CP56Time2a 的双点信息
		M_ST_TB_1	= 0x20,			// 带时标CP56Time2a 的步位置信息
		M_BO_TB_1	= 0x21,			// 带时标CP56Time2a 的32 比特串
		M_ME_TD_1	= 0x22,			// 带时标CP56Time2a 的测量值，规一化值
		M_ME_TE_1	= 0x23,			// 带时标CP56Time2a 的测量值，标度化值
		M_ME_TF_1	= 0x24,			// 带时标CP56Time2a 的测量值，短浮点数
		M_IT_TB_1	= 0x25,			// 带时标CP56Time2a 的累计量
		M_EP_TD_1	= 0x26,			// 带时标CP56Time2a 的继电保护装置事件
		M_EP_TE_1	= 0x27,			// 带时标CP56Time2a 的继电保护装置成组启动事件
		M_EP_TF_1	= 0x28,			// 带时标CP56Time2a 的继电保护装置成组出口信息

		// 控制方向
		C_SC_NA_1	= 0x2d,			// 单命令
		C_DC_NA_1	= 0x2e,			// 双命令
		C_RC_NA_1	= 0x2f,			// 升降命令
		C_SE_NA_1	= 0x30,			// 设点命令，规一化值
		C_SE_NB_1	= 0x31,			// 设点命令，标度化值
		C_SE_NC_1	= 0x32,			// 设点命令，短浮点数
		C_BO_NA_1	= 0x33,			// 32 比特串

		C_SC_NA_1_7	= 0x3a,			// 带时标CP56Time2a 的单命令
		C_DC_NA_1_7	= 0x3b,			// 带时标CP56Time2a 的双命令
		C_RC_NA_1_7	= 0x3c,			// 带时标CP56Time2a 的升降命令
		C_SE_TA_1_7	= 0x3d,			// 带时标CP56Time2a 的设点命令，规一化值
		C_SE_TB_1_7	= 0x3e,			// 带时标CP56Time2a 的设点命令，标度化值
		C_SE_TC_1_7	= 0x3f,			// 带时标CP56Time2a 的设点命令，短浮点数
		C_BO_NA_1_7	= 0x40,			// 带时标CP56Time2a 的32 比特串

		M_EI_NA_1	= 0x46,			// 初始化结束

		C_IC_NA_1	= 0x64,			// 总召唤命令
		C_CI_NA_1	= 0x65,			// 电能脉冲召唤命令
		C_RD_NA_1	= 0x66,			// 读命令
		C_CS_NA_1	= 0x67,			// 时钟同步命令
		C_RP_NA_1	= 0x69,			// 复位进程命令
		C_TS_NA_1	= 0x6b,			// 带时标CP56Time2a 的测试命令

		P_ME_NA_1	= 0x6e,			// 测量值参数，规一化值
		P_ME_NB_1	= 0x6f,			// 测量值参数，标度化值
		P_ME_NC_1	= 0x70,			// 测量值参数，短浮点数
		P_AC_NA_1	= 0x71,			// 参数激活

		F_FR_NA_1	= 0x78,			// 文件已准备好
		F_SR_NA_1	= 0x79,			// 节已准备好
		F_SC_NA_1	= 0x7a,			// 召唤目录，选择文件，召唤文件，召唤节
		F_LS_NA_1	= 0x7b,			// 最后的节，最后的段
		F_AF_NA_1	= 0x7c,			// 确认文件，确认节
		F_SG_NA_1	= 0x7d,			// 段
		F_DR_NA_1	= 0x7e,			// 目录
	};

	enum ECause{
			FACause_Undefined	= 0,	// 未用
			FACause_per		= 1,		// 周期,循环
			FACause_back	= 2,		// 背景扫描
			FACause_spont	= 3,		// 突发
			FACause_init	= 4,			// 初始化
			FACause_req		= 5,		// 请求或者被请求
			FACause_act		= 6,		// 激活
			FACause_actcon	= 7,		// 激活确认
			FACause_deact	= 8,		// 停止激活
			FACause_deactcon	= 9,	// 停止激活确认
			FACause_actterm	=10,		// 激活终止
			FACause_retrem	=11,		// 远方命令引起的返送信息
			FACause_retloc	= 12,		// 当地命令引起的返送信息
			FACause_file	= 13,			// 文件传输
			FACause_introgen	= 20,	// 响应站召唤
			FACause_inro1	= 21,		// 响应第1组召唤
			FACause_inro2	= 22,		// 响应第2组召唤
			FACause_inro3	= 23,		// 响应第3组召唤
			FACause_inro4	= 24,		// 响应第4组召唤
			FACause_inro5	= 25,		// 响应第5组召唤
			FACause_inro6	= 26,		// 响应第6组召唤
			FACause_inro7	= 27,		// 响应第7组召唤
			FACause_inro8	= 28,		// 响应第8组召唤
			FACause_inro9	= 29,		// 响应第9组召唤
			FACause_inro10	= 30,		// 响应第10组召唤
			FACause_inro11	= 31,		// 响应第11组召唤
			FACause_inro12	= 32,		// 响应第12组召唤
			FACause_inro13	= 33,		// 响应第13组召唤
			FACause_inro14	= 34,		// 响应第14组召唤
			FACause_inro15	= 35,		// 响应第15组召唤
			FACause_inro16	= 36,		// 响应第16组召唤
			FACause_reqcongen	= 37,	// 响应计数量站召唤
			FACause_reqco1	= 38,		// 响应第1组计数量站召唤
			FACause_reqco2	= 39,		// 响应第2组计数量站召唤
			FACause_reqco3	= 40,		// 响应第3组计数量站召唤
			FACause_reqco4	= 41,		// 响应第4组计数量站召唤

			FACause_unknowType	= 44,	// 未知的类型标识
			FACause_unknowCause	= 45,	// 未知的传输原因
			FACause_unknowComAd	= 46,	// 未知的应用服务数据单元公共地址
			FACause_unknowObjAd	= 47,	// 未知的信息对象地址
	};

	typedef dm::uint16 comm_addr_t;

	/**
	 * 带品质描述词的单点信息
	 */
	union USiq{
		dm::uint8 all;
		struct{
			dm::uint8 spi:1;	// 单点信息 0：开，1：合
			dm::uint8 res:3;
			dm::uint8 bl:1;	// 0:未被闭锁，1：被闭锁
			dm::uint8 sb:1;	// 0：未被取代，1：被取代
			dm::uint8 nt:1;	// 0：当前值，1：非当前值
			dm::uint8 iv:1;	// 0：有效，1：无效
		}bits;
	};

	/**
	 * 带品质描述词的双点信息
	 */
	union UDiq{
		dm::uint8 all;
		struct{
			dm::uint8 dpi:2;	// 0:不确定或中间态 1：确定状态开 2：确定状态合 3：不确定或中间态
			dm::uint8 res:2;
			dm::uint8 bl:1;	// 0:未被闭锁，1：被闭锁
			dm::uint8 sb:1;	// 0：未被取代，1：被取代
			dm::uint8 nt:1;	// 0：当前值，1：非当前值
			dm::uint8 iv:1;	// 0：有效，1：无效
		}bits;
	};

	/**
	 * 品质描述词
	 */
	union UQds{
		dm::uint8 all;
		struct{
			dm::uint8 ov:1; // 0:未溢出 1：溢出
			dm::uint8 res:3;
			dm::uint8 bl:1;	// 0:未被闭锁，1：被闭锁
			dm::uint8 sb:1;	// 0：未被取代，1：被取代
			dm::uint8 nt:1;	// 0：当前值，1：非当前值
			dm::uint8 iv:1;	// 0：有效，1：无效
		}bits;
	};

	/**
	 * 继电保护设备事件的品质描述词
	 */
	union UQdp{
		dm::uint8 all;
		struct{
			dm::uint8 res:3;
			dm::uint8 ei:1;	// 0:动作时间有效 1：动作时间无效
			dm::uint8 bl:1;	// 0:未被闭锁，1：被闭锁
			dm::uint8 sb:1;	// 0：未被取代，1：被取代
			dm::uint8 nt:1;	// 0：当前值，1：非当前值
			dm::uint8 iv:1;	// 0：有效，1：无效
		}bits;
	};

	/**
	 * 带瞬变状态指示的值，用于变压器的步位置或者其他步位置信息
	 */
	union UVti{
		dm::uint8 all;
		struct{
			dm::uint8 value:7;		// 值
			dm::uint8 transient:1;	// 0：设备未在瞬变状态 1：设备处于瞬变状态
		}bits;
	};

	/**
	 * 规一化值
	 */
	union UNva{
		dm::int16 all ;	// 用于表示-1～1之间的值 all/32767.0
		dm::uint8 bytes[2];
	} PACKED_SUF;

	/**
	 * 标度化值
	 */
	union USva{
		dm::int16 all;	// 用于表示-32768 32767
		dm::uint8 bytes[2];
	} PACKED_SUF;

	/**
	 * 短浮点数
	 */
	union UStd{
		dm::float32 all;
		dm::uint8 bytes[4];
	} PACKED_SUF;

	/**
	 * 二进制计数器读数
	 */
	union UBcr{
		dm::uint8 bytes[5];
		struct{
			dm::uint32 counterReading;	// 计数器读数
			dm::uint8 sq:5;				// 顺序号
			dm::uint8 cy:1;	// 进位 0：在相应的累加周期内计数器未溢出 1：计数器溢出
			dm::uint8 ca:1;	// 计数量被调整 0：上次读取后未被调整 1：被调整
			dm::uint8 iv:1;	// 0:有效 1：无效
		} PACKED_SUF bits;
	};

	/**
	 * 继电保护设备当个事件
	 */
	union USep{
		dm::uint8 all;
		struct{
			dm::uint8 es:2; // 事件状态 0：不确定 1：开 2：合 3：不确定
			dm::uint8 res:1;
			dm::uint8 ei:1;	// 0:动作时间有效 1：动作时间无效
			dm::uint8 bl:1;	// 0:未被闭锁，1：被闭锁
			dm::uint8 sb:1;	// 0：未被取代，1：被取代
			dm::uint8 nt:1;	// 0：当前值，1：非当前值
			dm::uint8 iv:1;	// 0：有效，1：无效
		}bits;
	};

	/**
	 * 继电保护设备启动事件
	 */
	union USep1{
		dm::uint8 all;
		struct{
			dm::uint8 gs:1;	// 总启动 0：无总启动 1：总启动
			dm::uint8 sl1:1;	// A相保护启动 0：无 1：启动
			dm::uint8 sl2:1;	// B相保护启动 0：无 1：启动
			dm::uint8 sl3:1;	// C相保护启动 0：无 1：启动
			dm::uint8 sie:1;	// 接地电流保护启动 0：无 1：启动
			dm::uint8 srd:1;	// 反向保护启动 0：未启动 1：启动
			dm::uint8 res:2;
		}bits;
	};

	/**
	 * 继电保护设备输出电路信息
	 */
	union UOci{
		dm::uint8 all;
		struct{
			dm::uint8 gs:1;	// 总启动 0：无总启动 1：总启动
			dm::uint8 sl1:1;	// A相保护启动 0：无 1：启动
			dm::uint8 sl2:1;	// B相保护启动 0：无 1：启动
			dm::uint8 sl3:1;	// C相保护启动 0：无 1：启动
			dm::uint8 res:4;
		}bits;
	};

	/**
	 * 二进制状态信息
	 */
	union UBsi{
		dm::uint32 bsi;	// 二进制状态信息
		dm::uint8 bytes[4];
	} PACKED_SUF;

	/**
	 * 固定测试字
	 */
	union UFbp{
		dm::uint16 fbp;
		dm::uint8 bytes[2];
	} PACKED_SUF;

	/**
	 * 单命令
	 */
	union USco{
		dm::uint8 all;
		struct{
			dm::uint8 scs:1;	// 0:开 1：合
			dm::uint8 res:1;
			dm::uint8 qoc:6;
		}bits;
	};

	/**
	 * 双命令
	 */
	union UDco{
		dm::uint8 all;
		struct{
			dm::uint8 dcs:2; // 双命令状态 0：不允许 1：开 2：合 3：不允许
			dm::uint8 qu:5;
			dm::uint8 se:1;  // 0:执行 1：选择
		}bits;
	};


	/**
	 * 步调节命令
	 */
	union URco{
		dm::uint8 all;
		struct{
			dm::uint8 rcs:2; // 步调节命令状态 0：不允许 1：降一步 2：升一步 3：不允许
			dm::uint8 qoc:6;
		}bits;
	};

	/**
	 * 七个八位位组二进制时间
	 */
	union UCp56Time2a{
		dm::uint8 bytes[7];
		struct{
			dm::uint16 ms;		// 毫秒 0~59 999
			dm::uint8 min:6;	// 0..59
			dm::uint8 res1:1;
			dm::uint8 iv:1;
			dm::uint8 hour:5;
			dm::uint8 res2:2;
			dm::uint8 su:1;
			dm::uint8 day:5;
			dm::uint8 wday:3;
			dm::uint8 mon:4;
			dm::uint8 res3:4;
			dm::uint8 year:7;
			dm::uint8 res4:1;
		} PACKED_SUF bits;
	};

	/**
	 * 三个八位位组二进制时间
	 */
	union UCp24Time2a{
		dm::uint8 bytes[3];
		struct{
			dm::uint16 ms;		// 毫秒 0~59 999
			dm::uint8 min:6;	// 0..59
			dm::uint8 res1:1;
			dm::uint8 iv:1;
		} PACKED_SUF;
	};

	/**
	 * 二个八位位组二进制时间
	 */
	union UCp16Time2a{
		dm::uint16 all;
		dm::uint8 bytes[2];
	} PACKED_SUF;

	/**
	 * 初始化原因
	 */
	union UCoi{
		dm::uint8 all;
		struct{
			dm::uint8 c:7;	// 0:当地电源合上 1：当地手动复位 2：远方复位 其他保留
			dm::uint8 b:1; // 0:未改变当地参数的初始化 1：改变当地参数后的初始化
		}bits;
	};

	/**
	 * 召唤限定词
	 */
	union UQoi{
		dm::uint8 all;	// 0:未用， 1～19：保留 20：总召唤 21：第1组召唤 ... 36:第16组召唤
	};

	/**
	 * 计数量召唤命令限定词
	 */
	union UQcc{
		dm::uint8 all;
		struct{
			dm::uint8 rqt:6;	// 请求 0：没有请求计数量 1：请求第1组 ... 4:请求第4组 5：总的请求计数量
			dm::uint8 frz:2;	// 冻结 0：读（无冻结或复位） 1：计数量冻结不带复位 2：计数量冻结带复位 3：计数量复位
		}bits;
	};

	/**
	 * 测量值参数限定词
	 */
	union UQpm{
		dm::uint8 all;
		struct{
			dm::uint8 kpa:6;	// 参数类别 0：未用 1：门限值 2：平滑系数 3：传送测量值的下限 4：传送测量值的上限
			dm::uint8 lpc:1;	// 当地参数改变 0：未改变 1：改变
			dm::uint8 pop:1;	// 参数在运行 0：运行 1：未运行
		}bits;
	};

	/**
	 * 参数激活限定词
	 */
	union UQpa{
		dm::uint8 all;	// 0:未用
							// 1：激活/停止激活这之前装载的参数
							// 2：激活/停止激活所寻址信息对象的参数
							// 3：激活/停止激活所寻址的持续循环或周期传输的信息对象
	};

	/**
	 * 命令限定词
	 */
	union UQoc{
	};

	/**
	 * 复位进程命令限定词
	 */
	union UQrp{
		dm::uint8 all;	// 0:未采用
							// 1：进程的总复位
							// 2：复位事件缓冲区等待处理的带时标信息
							// 其他：保留
	};

	/**
	 * 文件准备就绪限定词
	 */
	union UFrq{
		dm::uint8 all;
		struct{
			dm::uint8 b1:7; // 0:缺省 其他：保留
			dm::uint8 c:1;	// 确认 0：肯定确认 1：否定确认
		}bits;
	};

	/**
	 * 节准备就绪限定词
	 */
	union USrq{
		dm::uint8 all;
		struct{
			dm::uint8 b1:7;	// 0:缺省 其他：保留
			dm::uint8 r:1;		// 0:节准备就绪 1：节未准备就绪
		}bits;
	};

	/**
	 * 选择合召唤限定词
	 */
	union UScq{
		dm::uint8 all;
		struct{
			dm::uint8 u1:4;	// 0:缺省 1:选择文件 2:请求文件 3:停止激活文件 4:删除文件 5:选择节，6:请求节 7:停止激活节
			dm::uint8 u2:4;	// 0:缺省 1：无所请求的存储空间 2:校验和错 3:非所期望的通信复位
									// 4:非所期望的文件名 5：非所期望的节名
		};
	};

	/**
	 * 最后的节合段的限定词
	 */
	union ULsq{
		dm::uint8 all;	// 0:未用 1：不带停止激活的文件传输 2：带停止激活的文件传输
							// 3：不带停止激活的节传输 4：带停止激活的节传输
	};

	/**
	 * 文件认可或节认可限定词
	 */
	union UAfq{
		dm::uint8 all;
		struct{
			dm::uint8 u1:4;// 0:未用 1：文件传输的肯定认可 2：文件传输的否定认可
								// 3：节传输的肯定认可 4：节传输的否定认可
			dm::uint8 u2:4;	// 0:缺省 1：无所请求的存储空间 2：校验和错
									// 3:非所期望的通信服务 4：非所期望的文件名 5：非所期望的节名称
		}bits;
	};

	/**
	 * 文件名
	 */
	union UNof{
		dm::uint16 all;
		dm::uint8 bytes[2];
	} PACKED_SUF;

	/**
	 * 节名
	 */
	union UNos{
		dm::uint8 all;
	};

	/**
	 * 文件或节的长度
	 */
	union ULof{
		dm::uint8 bytes[3];
	};

	/*
	 * 段长度
	 */
	union ULos{
		dm::uint8 all;
	};

	/**
	 * 校验和
	 */
	union UChs{
		dm::uint8 all;
	};

	/**
	 * 文件的状态
	 */
	union USof{
		dm::uint8 all;
		struct{
			dm::uint8 status:5;	// 0:缺省 其他：保留
			dm::uint8 lfd:1;		// 0：后面还有目录文件 1:目录最后文件
			dm::uint8 For:1;		// 0：定义文件名 1：定义子目录名
			dm::uint8 fa:1;		// 0：文件等待传输 1：文件传输已激活
		}bits;
	};

	/**
	 * 设定命令限定词
	 */
	union UQos{
		dm::uint8 all;
		struct{
			dm::uint8 ql:7;	// 0:缺省 其他：保留
			dm::uint8 s_e:1;	// 0:执行 1：选择
		}bits;
	};

	/**
	 * 状态和状态变位检出
	 */
	union UScd{
		dm::uint8 bytes[4];
		struct{
			union{
				dm::uint16 st;
				struct{
					dm::uint16 st0:1;	// 0:开 1：合
					dm::uint16 st1:1;	// 0:开 1：合
					dm::uint16 st2:1;	// 0:开 1：合
					dm::uint16 st3:1;	// 0:开 1：合
					dm::uint16 st4:1;	// 0:开 1：合
					dm::uint16 st5:1;	// 0:开 1：合
					dm::uint16 st6:1;	// 0:开 1：合
					dm::uint16 st7:1;	// 0:开 1：合
					dm::uint16 st8:1;	// 0:开 1：合
					dm::uint16 st9:1;	// 0:开 1：合
					dm::uint16 st10:1;	// 0:开 1：合
					dm::uint16 st11:1;	// 0:开 1：合
					dm::uint16 st12:1;	// 0:开 1：合
					dm::uint16 st13:1;	// 0:开 1：合
					dm::uint16 st14:1;	// 0:开 1：合
					dm::uint16 st15:1;	// 0:开 1：合
				}bits;
			}st;
			union{
				dm::uint16 cd;
				struct{
					dm::uint16 cd0:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
					dm::uint16 cd1:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
					dm::uint16 cd2:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
					dm::uint16 cd3:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
					dm::uint16 cd4:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
					dm::uint16 cd5:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
					dm::uint16 cd6:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
					dm::uint16 cd7:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
					dm::uint16 cd8:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
					dm::uint16 cd9:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
					dm::uint16 cd10:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
					dm::uint16 cd11:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
					dm::uint16 cd12:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
					dm::uint16 cd13:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
					dm::uint16 cd14:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
					dm::uint16 cd15:1;	// 0:上次报告后未检出到状态变化 1：至少检测到一次变化
				}bits;
			}cd;
		} PACKED_SUF bits;
	};

	/**
	 * 必须基于ldu的缓冲区
	 */
	CFrame104Apdu( dm::uint8* buf,const dm::uint8& size );

	CFrame104Apdu& operator=( const CFrame104Apdu& apdu );

	inline void setType( const EType& type ){
		m_data[0] = type;
	}

	inline EType getType()const{
		return EType(m_data[0]);
	}

	inline bool isGroupObjs()const{
		return m_data[1] & 0x80;
	}

	inline void setGroupObjs( const bool& g=true ){
		if( g )
			m_data[1] |= 0x80;
		else
			m_data[1] &= 0x7F;
	}

	inline dm::uint8 getElementsCount()const{
		return m_data[1]&0x7F;
	}

	inline void setElementsCount( const dm::uint8& c ){
		m_data[1] = ((m_data[1]&0x80) | (c & 0x7F));
	}

	inline ECause getTransCause()const{
		return ECause(m_data[2]&0x3F);
	}

	inline void setCauseOfTrans( const ECause& cause ){
		m_data[2] = ((m_data[2]&0xC0)|(cause&0x3F));
		if( m_LenOfCause==2 )
			m_data[3] = 0;
	}

	inline bool isPn()const{
		return m_data[2]&0x40;
	}

	inline void setPn( const bool& s=true ){
		if( s )
			m_data[2] |= 0x40;
		else
			m_data[2] &= 0xBF;
	}

	inline bool isTest()const{
		return m_data[2]&0x80;
	}

	inline void setTest( const bool& s=true ){
		if( s )
			m_data[2] |= 0x80;
		else
			m_data[2] &= 0x7F;
	}

	// 这个函数只有在传送原因为2字节时，有意义
	inline const dm::uint8& getSourceAddr()const{
		return m_data[3];
	}

	inline void setSourceAddr( const dm::uint8& source ){
		if( m_LenOfCause==2 )
			m_data[3] = source;
	}

	inline const dm::uint8* getCommonAddressArray()const{
		return m_data+2+m_LenOfCause;
	}

	comm_addr_t getCommonAddress()const;

	inline void getCommonAddress( dm::uint8* address )const{
		address[0] = getCommonAddressArray()[0];
		if( m_LenOfCommonAddr==2 )
			address[1] = getCommonAddressArray()[1];
	}

	inline void setCommonAddress( const dm::uint8* address ){
		m_data[2 + m_LenOfCause] = address[0];
		if( m_LenOfCommonAddr==2 )
			m_data[3 + m_LenOfCause] = address[1];
	}

	void setCommonAddress( const comm_addr_t& addr );

	inline const dm::uint8& getLenOfCommonAddr()const{
		return m_LenOfCommonAddr;
	}

	bool checkCommonAddress( const dm::uint16& address )const;

	inline const dm::uint8& getLenOfCause()const{
		return m_LenOfCause;
	}

	inline const dm::uint8& getLenOfObjAddr()const{
		return m_LenOfObjAddr;
	}

	inline bool setLenOfCommonAddr( const dm::uint8& len ){
		if( len==1 || len==2 ){
			m_LenOfCommonAddr = len;
			m_commonLen = getCommonLen();
			return true;
		}
		return false;
	}

	inline bool setLenOfCause( const dm::uint8& len ){
		if( len==1 || len==2 ){
			m_LenOfCause = len;
			m_commonLen = getCommonLen();
			return true;
		}
		return false;
	}

	inline bool setLenOfObjAddr( const dm::uint8& len ){
		if( len==1 || len==2 || len==3 ){
			m_LenOfObjAddr = len;
			return true;
		}
		return false;
	}

	inline const dm::uint16& getMaxLenOfApdu()const{
		return m_maxLenOfApdu;
	}

	inline void setMaxLenOfApdu( dm::uint16 l ){
		m_maxLenOfApdu = l;
	}

	bool checkData( const dm::uint8& len );

	/**
	 * 获取当前APDU长度
	 * @return
	 */
	inline const dm::uint8& getLen()const{
		return m_len;
	}

	/**
	 * 获取信息对象数据长度
	 * @return
	 */
	inline dm::uint8 getElementLen()const{
		if( m_len<=m_commonLen )
			return 0;
		return m_len - m_commonLen;
	}

	/**
	 * 获取信息对象数据缓冲区地址
	 * @return
	 */
	inline const dm::uint8* getElements()const{
		return m_data + m_commonLen;
	}

	dm::uint8 getCommonLen()const{
		return 2 + m_LenOfCause + m_LenOfCommonAddr;
	}

	/**
	 * 设置整个APDU原始字节。一般用于APDU赋值
	 * @param buf
	 * @param len
	 * @param p
	 * @return
	 */
	bool setData( const dm::uint8* buf,const dm::uint8& len,const dm::uint8& p=0 );

	/**
	 * 获取APDU原始字节。一般用于APDU赋值
	 * @param p
	 * @return
	 */
	const dm::uint8* getData( const dm::uint8& p=0 )const;

	/**
	 * 获取整个APDU原始字节。一般用于APDU的赋值
	 * @param p
	 * @return
	 */
	dm::uint8* getData( const dm::uint8& p=0 );

	template<typename T>
	inline const T* getDataAs( const dm::uint8& p=0 )const{
		return (const T*)getData(p);
	}

	template<typename T>
	inline T* getDataAs( const dm::uint8& p=0 ){
		return (T*)getData(p);
	}

	template<typename T>
	inline const T* getElementAs( const dm::uint8& index )const{
		int p = getElementPos(sizeof(T),index);
		if( p<0 )
			return 0;
		return (T*) (m_data + m_commonLen + p);
	}

	template<typename T>
	inline T* getElementAs( const dm::uint8& index ){
		int p = getElementPos(sizeof(T),index);
		if( p<0 )
			return 0;
		return (T*) (m_data + m_commonLen + p);
	}

	int getElementPos( int elementSize,const dm::uint8& index )const;

	/****************************************
	 * 应用数据处理
	 ****************************************/

	/********* 不带时标的单点信息 *********/

	inline bool checkInfo_1_M_SP_NA_1()const{
		return checkInfo(sizeof(USiq));
	}

	inline dm::uint32 getInfoAddr_1_M_SP_NA_1( const int& obj=0 )const{
		return getInfoAddr(sizeof(USiq),obj);
	}

	inline const USiq* getInfo_1_M_SP_NA_1( const int& obj )const{
		return (const USiq*)getInfo(sizeof(USiq),obj);
	}

	inline void makeInfo_1_M_SP_NA_1( const bool& group,const dm::uint8& elemCount ){
		makeInfo(sizeof(USiq),group,elemCount);
	}

	inline void setInfoAddr_1_M_SP_NA_1( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr( sizeof(USiq),objAddr,obj);
	}

	inline USiq* getInfo_1_M_SP_NA_1( const int& obj ){
		return (USiq*) getInfo(sizeof(USiq),obj);
	}

	/********* 带时标的单点信息 *********/
	inline bool checkInfo_2_M_SP_TA_1()const{
		return checkInfo(sizeof(USiq)+sizeof(UCp24Time2a));
	}

	inline dm::uint32 getInfoAddr_2_M_SP_TA_1( const int& obj=0 )const{
		return getInfoAddr(sizeof(USiq)+sizeof(UCp24Time2a),obj);
	}

	inline const USiq* getInfo_2_M_SP_TA_1( const int& obj )const{
		return (const USiq*)getInfo(sizeof(USiq)+sizeof(UCp24Time2a),obj);
	}

	inline const UCp24Time2a* getInfo_2_M_SP_TA_1_time( const int& obj )const{
		return (const UCp24Time2a*)(getInfo(sizeof(USiq)+sizeof(UCp24Time2a),obj)+sizeof(USiq));
	}

	inline void makeInfo_2_M_SP_TA_1(const dm::uint8& elemCount ){
		makeInfo(sizeof(USiq)+sizeof(UCp24Time2a),false,elemCount);
	}

	inline void setInfoAddr_2_M_SP_TA_1( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr( sizeof(USiq)+sizeof(UCp24Time2a),objAddr,obj);
	}

	inline USiq* getInfo_2_M_SP_TA_1( const int& obj ){
		return (USiq*) getInfo(sizeof(USiq)+sizeof(UCp24Time2a),obj);
	}

	inline UCp24Time2a* getInfo_2_M_SP_TA_1_time( const int& obj ){
		return (UCp24Time2a*)(getInfo(sizeof(USiq)+sizeof(UCp24Time2a),obj)+sizeof(USiq));
	}

	/********* 不带时标的双点信息 *********/

	inline bool checkInfo_3_M_DP_NA_1()const{
		return checkInfo(sizeof(UDiq));
	}

	inline dm::uint32 getInfoAddr_3_M_DP_NA_1( const int& obj=0 )const{
		return getInfoAddr(sizeof(UDiq),obj);
	}

	inline const UDiq* getInfo_3_M_DP_NA_1( const int& obj )const{
		return (const UDiq*)getInfo(sizeof(UDiq),obj);
	}

	inline void makeInfo_3_M_DP_NA_1( const bool& group,const dm::uint8& elemCount ){
		makeInfo(sizeof(UDiq),group,elemCount);
	}

	inline void setInfoAddr_3_M_DP_NA_1( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr( sizeof(UDiq),objAddr,obj);
	}

	inline UDiq* getInfo_3_M_DP_NA_1( const int& obj ){
		return (UDiq*) getInfo(sizeof(UDiq),obj);
	}

	/**
	 * 状态量
	 * @param count
	 * @param startNo
	 * @param cause
	 */
	inline void makeFrame_3_M_DP_NA_1( const dm::uint8& count,const dm::uint32& startNo,const ECause& cause = FACause_act ){
		setType( M_DP_NA_1 );
		makeInfo<UDiq>(true,count);
		setCauseOfTrans(cause);
		setInfoAddr<UDiq>(startNo);
	}

	/********* 带时标的双点信息 *********/
	inline bool checkInfo_4_M_DP_TA_1()const{
		return checkInfo(sizeof(UDiq)+sizeof(UCp24Time2a));
	}

	inline dm::uint32 getInfoAddr_4_M_DP_TA_1( const int& obj=0 )const{
		return getInfoAddr(sizeof(UDiq)+sizeof(UCp24Time2a),obj);
	}

	inline const UDiq* getInfo_4_M_DP_TA_1( const int& obj )const{
		return (const UDiq*)getInfo(sizeof(UDiq)+sizeof(UCp24Time2a),obj);
	}

	inline const UCp24Time2a* getInfo_4_M_DP_TA_1_time( const int& obj )const{
		return (const UCp24Time2a*)(getInfo(sizeof(UDiq)+sizeof(UCp24Time2a),obj)+sizeof(UDiq));
	}

	inline void makeInfo_4_M_DP_TA_1(const dm::uint8& elemCount ){
		makeInfo(sizeof(UDiq)+sizeof(UCp24Time2a),false,elemCount);
	}

	inline void setInfoAddr_4_M_DP_TA_1( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr( sizeof(UDiq)+sizeof(UCp24Time2a),objAddr,obj);
	}

	inline UDiq* getInfo_4_M_DP_TA_1( const int& obj ){
		return (UDiq*) getInfo(sizeof(UDiq)+sizeof(UCp24Time2a),obj);
	}

	inline UCp24Time2a* getInfo_4_M_DP_TA_1_time( const int& obj ){
		return (UCp24Time2a*)(getInfo(sizeof(UDiq)+sizeof(UCp24Time2a),obj)+sizeof(UDiq));
	}

	/********* 测量值，规一化值 *********/

	inline bool checkInfo_9_M_ME_NA_1()const{
		return checkInfo(sizeof(UNva)+sizeof(UQds));
	}

	inline dm::uint32 getInfoAddr_9_M_ME_NA_1( const int& obj=0 )const{
		return getInfoAddr(sizeof(UNva)+sizeof(UQds),obj);
	}

	inline const UNva* getInfo_9_M_ME_NA_1( const int& obj )const{
		return (const UNva*)getInfo(sizeof(UNva)+sizeof(UQds),obj);
	}

	inline const UQds* getInfo_9_M_ME_NA_1_qds( const int& obj )const{
		return (const UQds*)(getInfo(sizeof(UNva)+sizeof(UQds),obj)+sizeof(UNva));
	}

	inline void makeInfo_9_M_ME_NA_1(const dm::uint8& elemCount ){
		makeInfo(sizeof(UNva)+sizeof(UQds),false,elemCount);
	}

	inline void setInfoAddr_9_M_ME_NA_1( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr( sizeof(UNva)+sizeof(UQds),objAddr,obj);
	}

	inline UNva* getInfo_9_M_ME_NA_1( const int& obj ){
		return (UNva*) getInfo(sizeof(UNva)+sizeof(UQds),obj);
	}

	inline UQds* getInfo_9_M_ME_NA_1_qds( const int& obj ){
		return (UQds*)(getInfo(sizeof(UNva)+sizeof(UQds),obj)+sizeof(UNva));
	}

	/********* 测量值，带时标的规一化值 *********/
	inline bool checkInfo_10_M_ME_TA_1()const{
		return checkInfo(sizeof(UNva)+sizeof(UQds)+sizeof(UCp24Time2a));
	}

	inline dm::uint32 getInfoAddr_10_M_ME_TA_1( const int& obj=0 )const{
		return getInfoAddr(sizeof(UNva)+sizeof(UQds)+sizeof(UCp24Time2a),obj);
	}

	inline const UNva* getInfo_10_M_ME_TA_1( const int& obj )const{
		return (const UNva*)getInfo(sizeof(UNva)+sizeof(UQds)+sizeof(UCp24Time2a),obj);
	}

	inline const UQds* getInfo_10_M_ME_TA_1_qds( const int& obj )const{
		return (UQds*)(getInfo(sizeof(UNva)+sizeof(UQds)+sizeof(UCp24Time2a),obj)+sizeof(UNva));
	}

	inline const UCp24Time2a* getInfo_10_M_ME_TA_1_time( const int& obj )const{
		return (const UCp24Time2a*)(getInfo(sizeof(UNva)+sizeof(UQds)+sizeof(UCp24Time2a),obj)+sizeof(UNva)+sizeof(UQds));
	}

	inline void makeInfo_10_M_ME_TA_1(const dm::uint8& elemCount ){
		makeInfo(sizeof(UNva)+sizeof(UQds)+sizeof(UCp24Time2a),false,elemCount);
	}

	inline void setInfoAddr_10_M_ME_TA_1( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr( sizeof(UNva)+sizeof(UQds)+sizeof(UCp24Time2a),objAddr,obj);
	}

	inline UNva* getInfo_10_M_ME_TA_1( const int& obj ){
		return (UNva*) getInfo(sizeof(UNva)+sizeof(UQds)+sizeof(UCp24Time2a),obj);
	}

	inline UQds* getInfo_10_M_ME_TA_1_qds( const int& obj ){
		return (UQds*)(getInfo(sizeof(UNva)+sizeof(UQds)+sizeof(UCp24Time2a),obj)+sizeof(UNva));
	}

	inline UCp24Time2a* getInfo_10_M_ME_TA_1_time( const int& obj ){
		return (UCp24Time2a*)(getInfo(sizeof(UNva)+sizeof(UQds)+sizeof(UCp24Time2a),obj)+sizeof(UNva)+sizeof(UQds));
	}

	/********* 测量值，标度化值 *********/

	inline bool checkInfo_11_M_ME_NB_1()const{
		return checkInfo(sizeof(USva)+sizeof(UQds));
	}

	inline dm::uint32 getInfoAddr_11_M_ME_NB_1( const int& obj=0 )const{
		return getInfoAddr(sizeof(USva)+sizeof(UQds),obj);
	}

	inline const USva* getInfo_11_M_ME_NB_1( const int& obj )const{
		return (const USva*)getInfo(sizeof(USva)+sizeof(UQds),obj);
	}

	inline const UQds* getInfo_11_M_ME_NB_1_qds( const int& obj )const{
		return (const UQds*)(getInfo(sizeof(USva)+sizeof(UQds),obj)+sizeof(USva));
	}

	inline void makeInfo_11_M_ME_NB_1(const dm::uint8& elemCount ){
		makeInfo(sizeof(USva)+sizeof(UQds),false,elemCount);
	}

	inline void setInfoAddr_11_M_ME_NB_1( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr( sizeof(USva)+sizeof(UQds),objAddr,obj);
	}

	inline USva* getInfo_11_M_ME_NB_1( const int& obj ){
		return (USva*) getInfo(sizeof(USva)+sizeof(UQds),obj);
	}

	inline UQds* getInfo_11_M_ME_NB_1_qds( const int& obj ){
		return (UQds*)(getInfo(sizeof(USva)+sizeof(UQds),obj)+sizeof(USva));
	}

	/**
	 * 离散量
	 * @param count
	 * @param startNo
	 * @param cause
	 */
	inline void makeFrame_11_M_ME_NB_1( const dm::uint8& count,const dm::uint32& startNo,const ECause& cause = FACause_act ){
		setType( M_ME_NB_1 );
		makeInfo(sizeof(USva)+sizeof(UQds),true,count);
		setCauseOfTrans(cause);
		setInfoAddr(sizeof(USva)+sizeof(UQds),startNo);
	}

	/********* 测量值，带时标的标度化值 *********/
	inline bool checkInfo_12_M_ME_TB_1()const{
		return checkInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp24Time2a));
	}

	inline dm::uint32 getInfoAddr_12_M_ME_TB_1( const int& obj=0 )const{
		return getInfoAddr(sizeof(USva)+sizeof(UQds)+sizeof(UCp24Time2a),obj);
	}

	inline const USva* getInfo_12_M_ME_TB_1( const int& obj )const{
		return (const USva*)getInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp24Time2a),obj);
	}

	inline const UQds* getInfo_12_M_ME_TB_1_qds( const int& obj )const{
		return (UQds*)(getInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp24Time2a),obj)+sizeof(USva));
	}

	inline const UCp24Time2a* getInfo_12_M_ME_TB_1_time( const int& obj )const{
		return (const UCp24Time2a*)(getInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp24Time2a),obj)+sizeof(USva)+sizeof(UQds));
	}

	inline void makeInfo_12_M_ME_TB_1(const dm::uint8& elemCount ){
		makeInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp24Time2a),false,elemCount);
	}

	inline void setInfoAddr_12_M_ME_TB_1( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr( sizeof(USva)+sizeof(UQds)+sizeof(UCp24Time2a),objAddr,obj);
	}

	inline USva* getInfo_12_M_ME_TB_1( const int& obj ){
		return (USva*) getInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp24Time2a),obj);
	}

	inline UQds* getInfo_12_M_ME_TB_1_qds( const int& obj ){
		return (UQds*)(getInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp24Time2a),obj)+sizeof(USva));
	}

	inline UCp24Time2a* getInfo_12_M_ME_TB_1_time( const int& obj ){
		return (UCp24Time2a*)(getInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp24Time2a),obj)+sizeof(USva)+sizeof(UQds));
	}

	/********* 测量值，短浮点数 *********/

	inline bool checkInfo_13_M_ME_NC_1()const{
		return checkInfo(sizeof(UStd)+sizeof(UQds));
	}

	inline dm::uint32 getInfoAddr_13_M_ME_NC_1( const int& obj=0 )const{
		return getInfoAddr(sizeof(UStd)+sizeof(UQds),obj);
	}

	inline const UStd* getInfo_13_M_ME_NC_1( const int& obj )const{
		return (const UStd*)getInfo(sizeof(UStd)+sizeof(UQds),obj);
	}

	inline const UQds* getInfo_13_M_ME_NC_1_qds( const int& obj )const{
		return (const UQds*)(getInfo(sizeof(UStd)+sizeof(UQds),obj)+sizeof(UStd));
	}

	inline void makeInfo_13_M_ME_NC_1(const dm::uint8& elemCount ){
		makeInfo(sizeof(UStd)+sizeof(UQds),false,elemCount);
	}

	inline void setInfoAddr_13_M_ME_NC_1( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr( sizeof(UStd)+sizeof(UQds),objAddr,obj);
	}

	inline UStd* getInfo_13_M_ME_NC_1( const int& obj ){
		return (UStd*) getInfo(sizeof(UStd)+sizeof(UQds),obj);
	}

	inline UQds* getInfo_13_M_ME_NC_1_qds( const int& obj ){
		return (UQds*)(getInfo(sizeof(UStd)+sizeof(UQds),obj)+sizeof(UStd));
	}

	/**
	 * 测量量
	 * @param count
	 * @param startNo
	 * @param cause
	 */
	inline void makeFrame_13_M_ME_NC_1( const dm::uint8& count,const dm::uint32& startNo,const ECause& cause = FACause_act ){
		setType( M_ME_NC_1 );
		makeInfo(sizeof(UStd)+sizeof(UQds),true,count);
		setCauseOfTrans(cause);
		setInfoAddr(sizeof(UStd)+sizeof(UQds),startNo);
	}

	/********* 测量值，带时标的短浮点数 *********/
	inline bool checkInfo_14_M_ME_TC_1()const{
		return checkInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp24Time2a));
	}

	inline dm::uint32 getInfoAddr_14_M_ME_TC_1( const int& obj=0 )const{
		return getInfoAddr(sizeof(UStd)+sizeof(UQds)+sizeof(UCp24Time2a),obj);
	}

	inline const UStd* getInfo_14_M_ME_TC_1( const int& obj )const{
		return (const UStd*)getInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp24Time2a),obj);
	}

	inline const UQds* getInfo_14_M_ME_TC_1_qds( const int& obj )const{
		return (UQds*)(getInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp24Time2a),obj)+sizeof(UStd));
	}

	inline const UCp24Time2a* getInfo_14_M_ME_TC_1_time( const int& obj )const{
		return (const UCp24Time2a*)(getInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp24Time2a),obj)+sizeof(UStd)+sizeof(UQds));
	}

	inline void makeInfo_14_M_ME_TC_1(const dm::uint8& elemCount ){
		makeInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp24Time2a),false,elemCount);
	}

	inline void setInfoAddr_14_M_ME_TC_1( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr( sizeof(UStd)+sizeof(UQds)+sizeof(UCp24Time2a),objAddr,obj);
	}

	inline UStd* getInfo_14_M_ME_TC_1( const int& obj ){
		return (UStd*) getInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp24Time2a),obj);
	}

	inline UQds* getInfo_14_M_ME_TC_1_qds( const int& obj ){
		return (UQds*)(getInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp24Time2a),obj)+sizeof(UStd));
	}

	inline UCp24Time2a* getInfo_14_M_ME_TC_1_time( const int& obj ){
		return (UCp24Time2a*)(getInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp24Time2a),obj)+sizeof(UStd)+sizeof(UQds));
	}

	/********* 累计量 *********/
	inline bool checkInfo_15_M_IT_NA_1()const{
		return checkInfo(sizeof(UBcr));
	}

	inline dm::uint32 getInfoAddr_15_M_IT_NA_1( const int& obj=0 )const{
		return getInfoAddr(sizeof(UBcr),obj);
	}

	inline const UBcr* getInfo_15_M_IT_NA_1( const int& obj )const{
		return (const UBcr*)getInfo(sizeof(UBcr),obj);
	}

	inline void makeInfo_15_M_IT_NA_1(const dm::uint8& elemCount ){
		makeInfo(sizeof(UBcr),false,elemCount);
	}

	inline void setInfoAddr_15_M_IT_NA_1( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr( sizeof(UBcr),objAddr,obj);
	}

	inline UBcr* getInfo_15_M_IT_NA_1( const int& obj ){
		return (UBcr*) getInfo(sizeof(UBcr),obj);
	}

	/**
	 * 累计量
	 * @param count
	 * @param startNo
	 * @param cause
	 */
	inline void makeFrame_15_M_IT_NA_1( const dm::uint8& count,const dm::uint32& startNo,const ECause& cause = FACause_act ){
		setType( M_IT_NA_1 );
		makeInfo(sizeof(UBcr),true,count);
		setCauseOfTrans(cause);
		setInfoAddr(sizeof(UBcr),startNo);
	}

	/********* 带时标的双点信息 ***********/
	inline bool checkInfo_31_M_DP_TB_1()const{
		return checkInfo(sizeof(UDiq)+sizeof(UCp56Time2a));
	}

	inline dm::uint32 getInfoAddr_31_M_DP_TB_1( const int& obj=0 )const{
		return getInfoAddr(sizeof(UDiq)+sizeof(UCp56Time2a),obj);
	}

	inline const UDiq* getInfo_31_M_DP_TB_1_qid( const int& obj )const{
		return (const UDiq*)getInfo(sizeof(UDiq)+sizeof(UCp56Time2a),obj);
	}

	inline const UCp56Time2a* getInfo_31_M_DP_TB_1_time( const int& obj )const{
		return (const UCp56Time2a*)(getInfo(sizeof(UDiq)+sizeof(UCp56Time2a),obj)+sizeof(UDiq));
	}

	inline void makeInfo_31_M_DP_TB_1(const dm::uint8& elemCount ){
		makeInfo(sizeof(UDiq)+sizeof(UCp56Time2a),false,elemCount);
	}

	inline void setInfoAddr_31_M_DP_TB_1( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr( sizeof(UDiq)+sizeof(UCp56Time2a),objAddr,obj);
	}

	inline UDiq* getInfo_31_M_DP_TB_1_qid( const int& obj ){
		return (UDiq*) getInfo(sizeof(UDiq)+sizeof(UCp56Time2a),obj);
	}

	inline UCp56Time2a* getInfo_31_M_DP_TB_1_time( const int& obj ){
		return (UCp56Time2a*)(getInfo(sizeof(UDiq)+sizeof(UCp56Time2a),obj)+sizeof(UDiq));
	}

	/********* 带时标的测量值 标度化值 ***********/
	inline bool checkInfo_35_M_ME_TE_1()const{
		return checkInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp56Time2a));
	}

	inline dm::uint32 getInfoAddr_35_M_ME_TE_1( const int& obj=0 )const{
		return getInfoAddr(sizeof(USva)+sizeof(UQds)+sizeof(UCp56Time2a),obj);
	}

	inline const USva* getInfo_35_M_ME_TE_1_sva( const int& obj )const{
		return (const USva*)getInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp56Time2a),obj);
	}

	inline const UQds* getInfo_35_M_ME_TE_1_qds( const int& obj )const{
		return (const UQds*)(getInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp56Time2a),obj)+sizeof(USva));
	}

	inline const UCp56Time2a* getInfo_35_M_ME_TE_1_time( const int& obj )const{
		return (const UCp56Time2a*)(getInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp56Time2a),obj)+sizeof(USva)+sizeof(UQds));
	}

	inline void makeInfo_35_M_ME_TE_1(const dm::uint8& elemCount ){
		makeInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp56Time2a),false,elemCount);
	}

	inline void setInfoAddr_35_M_ME_TE_1( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr( sizeof(USva)+sizeof(UQds)+sizeof(UCp56Time2a),objAddr,obj);
	}

	inline USva* getInfo_35_M_ME_TE_1_sva( const int& obj ){
		return (USva*) getInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp56Time2a),obj);
	}

	inline UQds* getInfo_35_M_ME_TE_1_qds( const int& obj ){
		return (UQds*) (getInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp56Time2a),obj) + sizeof(USva));
	}

	inline UCp56Time2a* getInfo_35_M_ME_TE_1_time( const int& obj ){
		return (UCp56Time2a*)(getInfo(sizeof(USva)+sizeof(UQds)+sizeof(UCp56Time2a),obj)+sizeof(USva)+sizeof(UQds));
	}

	/********* 带时标的测量值 短浮点数 ***********/
	inline bool checkInfo_36_M_ME_TF_1()const{
		return checkInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp56Time2a));
	}

	inline dm::uint32 getInfoAddr_36_M_ME_TF_1( const int& obj=0 )const{
		return getInfoAddr(sizeof(UStd)+sizeof(UQds)+sizeof(UCp56Time2a),obj);
	}

	inline const UStd* getInfo_36_M_ME_TF_1_std( const int& obj )const{
		return (const UStd*)getInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp56Time2a),obj);
	}

	inline const UQds* getInfo_36_M_ME_TF_1_qds( const int& obj )const{
		return (const UQds*)(getInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp56Time2a),obj)+sizeof(UStd));
	}

	inline const UCp56Time2a* getInfo_36_M_ME_TF_1_time( const int& obj )const{
		return (const UCp56Time2a*)(getInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp56Time2a),obj)+sizeof(UStd)+sizeof(UQds));
	}

	inline void makeInfo_36_M_ME_TF_1(const dm::uint8& elemCount ){
		makeInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp56Time2a),false,elemCount);
	}

	inline void setInfoAddr_36_M_ME_TF_1( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr( sizeof(UStd)+sizeof(UQds)+sizeof(UCp56Time2a),objAddr,obj);
	}

	inline UStd* getInfo_36_M_ME_TF_1_std( const int& obj ){
		return (UStd*) getInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp56Time2a),obj);
	}

	inline UQds* getInfo_36_M_ME_TF_1_qds( const int& obj ){
		return (UQds*) (getInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp56Time2a),obj) + sizeof(UStd));
	}

	inline UCp56Time2a* getInfo_36_M_ME_TF_1_time( const int& obj ){
		return (UCp56Time2a*)(getInfo(sizeof(UStd)+sizeof(UQds)+sizeof(UCp56Time2a),obj)+sizeof(UStd)+sizeof(UQds));
	}

	/********* 带时标的累计量 ***********/
	inline bool checkInfo_37_M_IT_TB_1()const{
		return checkInfo(sizeof(UBcr)+sizeof(UCp56Time2a));
	}

	inline dm::uint32 getInfoAddr_37_M_IT_TB_1( const int& obj=0 )const{
		return getInfoAddr(sizeof(UBcr)+sizeof(UCp56Time2a),obj);
	}

	inline const UBcr* getInfo_37_M_IT_TB_1_bcr( const int& obj )const{
		return (const UBcr*)getInfo(sizeof(UBcr)+sizeof(UCp56Time2a),obj);
	}

	inline const UCp56Time2a* getInfo_37_M_IT_TB_1_time( const int& obj )const{
		return (const UCp56Time2a*)(getInfo(sizeof(UBcr)+sizeof(UCp56Time2a),obj)+sizeof(UBcr));
	}

	inline void makeInfo_37_M_IT_TB_1(const dm::uint8& elemCount ){
		makeInfo(sizeof(UBcr)+sizeof(UCp56Time2a),false,elemCount);
	}

	inline void setInfoAddr_37_M_IT_TB_1( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr( sizeof(UBcr)+sizeof(UCp56Time2a),objAddr,obj);
	}

	inline UBcr* getInfo_37_M_IT_TB_1_std( const int& obj ){
		return (UBcr*) getInfo(sizeof(UBcr)+sizeof(UCp56Time2a),obj);
	}

	inline UCp56Time2a* getInfo_37_M_IT_TB_1_time( const int& obj ){
		return (UCp56Time2a*)(getInfo(sizeof(UBcr)+sizeof(UCp56Time2a),obj)+sizeof(UBcr));
	}

	/********* 总召命令 *********/

	inline bool checkInfo_100_C_IC_NA_1()const{
		return checkInfo(sizeof(UQoi));
	}

	inline dm::uint32 getInfoAddr_100_C_IC_NA_1()const{
		return getInfoAddr(sizeof(UQoi));
	}

	inline const UQoi* getInfo_100_C_IC_NA_1()const{
		return getInfo<UQoi>(0);
	}

	inline void makeInfo_100_C_IC_NA_1(){
		makeInfo(sizeof(UQoi),false,1);
	}

	inline void setInfoAddr_100_C_IC_NA_1(){
		setInfoAddr( sizeof(UQoi),0);
	}

	inline UQoi* getInfo_100_C_IC_NA_1(){
		return getInfo<UQoi>(0);
	}

	inline void makeFrame_100_C_IC_NA_1( const dm::uint8& group=0,const ECause& cause = FACause_act ){
		setType( C_IC_NA_1 );
		makeInfo<UQoi>(false,1);
		setCauseOfTrans(cause);
		setInfoAddr<UQoi>(0);
		getInfo<UQoi>(0)->all = group;
	}

	/********** 双命令 *********/

	inline bool checkInfo_46_C_DC_NA_1()const{
		return checkInfo(sizeof(UDco));
	}

	inline dm::uint32 getInfoAddr_46_C_DC_NA_1()const{
		return getInfoAddr(sizeof(UDco));
	}

	inline const UDco* getInfo_46_C_DC_NA_1()const{
		return getInfo<UDco>(0);
	}

	inline void makeInfo_46_C_DC_NA_1(){
		makeInfo(sizeof(UDco),false,1);
	}

	inline void setInfoAddr_46_C_DC_NA_1(){
		setInfoAddr( sizeof(UDco),0);
	}

	inline UDco* getInfo_46_C_DC_NA_1(){
		return getInfo<UDco>(0);
	}

	inline void makeFrame_46_C_DC_NA_1( const dm::uint32& no,const bool& on,const bool& select,const ECause& cause = FACause_act ){
		setType( C_DC_NA_1 );
		makeInfo<UDco>(false,1);
		setCauseOfTrans(cause);
		setInfoAddr<UDco>(no);
		getInfo<UDco>(0)->bits.dcs = on?2:1;
		getInfo<UDco>(0)->bits.qu = 0;
		getInfo<UDco>(0)->bits.se = select?1:0;
	}

	/********** 设定命令 *********/

	inline void makeFrame_48_C_SE_NA_1( const dm::uint32& no,const dm::uint16& v,const ECause& cause = FACause_act ){
		setType( C_SE_NA_1 );
		makeInfo(sizeof(UNva)+sizeof(UQos),false,1);
		setCauseOfTrans(cause);
		setInfoAddr(sizeof(UNva)+sizeof(UQos),no);
		getDataAs<UNva>(0)->all = v;
		getDataAs<UQos>(sizeof(UNva))->bits.ql = 0;
		getDataAs<UQos>(sizeof(UNva))->bits.s_e = 0;
	}

	/********** 计量量召唤命令 *********/

	inline bool checkInfo_101_C_CI_NA_1()const{
		return checkInfo(sizeof(UQcc));
	}

	inline dm::uint32 getInfoAddr_101_C_CI_NA_1()const{
		return getInfoAddr(sizeof(UQcc));
	}

	inline const UQcc* getInfo_101_C_CI_NA_1()const{
		return (const UQcc*)getInfo(sizeof(UQcc),0);
	}

	inline void makeInfo_101_C_CI_NA_1(){
		makeInfo(sizeof(UQcc),false,1);
	}

	inline void setInfoAddr_101_C_CI_NA_1(){
		setInfoAddr( sizeof(UQcc),0);
	}

	inline UQcc* getInfo_101_C_CI_NA_1(){
		return (UQcc*)getInfo(sizeof(UQcc),0);
	}

	/********** 读命令 *********/

	inline void makeFrame_102_C_RD_NA_1( const dm::uint32& no,const ECause& cause = FACause_act ){
		setType( C_RD_NA_1 );
		makeInfo(0,false,1);
		setCauseOfTrans(cause);
		setInfoAddr(0,no);
	}

	/********** 时钟同步命令 *********/

	inline bool checkInfo_103_C_CS_NA_1()const{
		return checkInfo(sizeof(UCp56Time2a));
	}

	inline dm::uint32 getInfoAddr_103_C_CS_NA_1()const{
		return getInfoAddr(sizeof(UCp56Time2a));
	}

	inline const UCp56Time2a* getInfo_103_C_CS_NA_1()const{
		return getInfo<UCp56Time2a>(0);
	}

	inline void makeInfo_103_C_CS_NA_1(){
		makeInfo(sizeof(UCp56Time2a),false,1);
	}

	inline void setInfoAddr_103_C_CS_NA_1(){
		setInfoAddr( sizeof(UCp56Time2a),0);
	}

	inline UCp56Time2a* getInfo_103_C_CS_NA_1(){
		return getInfo<UCp56Time2a>(0);
	}

	inline void makeFrame_103_C_CS_NA_1(
			const dm::uint8& year,const dm::uint8& mon,const dm::uint8& day,const dm::uint8& wday,
			const dm::uint8& hour,const dm::uint8& min,const dm::uint16& msec,
			const ECause& cause = FACause_act ){
		setType( C_CS_NA_1 );
		makeInfo<UCp56Time2a>(false,1);
		setCauseOfTrans(cause);
		setInfoAddr<UCp56Time2a>(0);
		getInfo<UCp56Time2a>(0)->bits.year = year;
		getInfo<UCp56Time2a>(0)->bits.mon = mon;
		getInfo<UCp56Time2a>(0)->bits.day = day;
		getInfo<UCp56Time2a>(0)->bits.wday = wday;
		getInfo<UCp56Time2a>(0)->bits.hour = hour;
		getInfo<UCp56Time2a>(0)->bits.min = min;
		getInfo<UCp56Time2a>(0)->bits.ms = msec;
	}

	inline void makeFrame_103_C_CS_NA_1(
			const UCp56Time2a& t,
			const ECause& cause = FACause_act ){
		setType( C_CS_NA_1 );
		makeInfo<UCp56Time2a>(false,1);
		setCauseOfTrans(cause);
		setInfoAddr<UCp56Time2a>(0);
		getInfo<UCp56Time2a>(0)->bits.year = t.bits.year;
		getInfo<UCp56Time2a>(0)->bits.mon = t.bits.mon;
		getInfo<UCp56Time2a>(0)->bits.day = t.bits.day;
		getInfo<UCp56Time2a>(0)->bits.hour = t.bits.hour;
		getInfo<UCp56Time2a>(0)->bits.min = t.bits.min;
		getInfo<UCp56Time2a>(0)->bits.ms = t.bits.ms;
	}

	/********** 测量值参数：标度化值 *********/

	inline bool checkInfo_111_P_ME_NB_1()const{
		return checkInfo(sizeof(USva)+sizeof(UQpm));
	}

	inline dm::uint32 getInfoAddr_111_P_ME_NB_1()const{
		return getInfoAddr(sizeof(USva)+sizeof(UQpm));
	}

	inline const USva* getInfo_111_P_ME_NB_1_sva()const{
		return (const USva*)getInfo(sizeof(USva)+sizeof(UQpm),0);
	}

	inline const UQpm* getInfo_111_P_ME_NB_1_qpm()const{
		return (const UQpm*)(getInfo(sizeof(USva)+sizeof(UQpm),0)+sizeof(USva));
	}

	inline void makeInfo_111_P_ME_NB_1(){
		makeInfo(sizeof(USva)+sizeof(UQpm),false,1);
	}

	inline void setInfoAddr_111_P_ME_NB_1(){
		setInfoAddr( sizeof(USva)+sizeof(UQpm),0);
	}

	inline USva* getInfo_111_P_ME_NB_1(){
		return (USva*)getInfo(sizeof(USva)+sizeof(UQpm),0);
	}

	inline UQpm* getInfo_111_P_ME_NB_1_qpm(){
		return (UQpm*)(getInfo(sizeof(USva)+sizeof(UQpm),0)+sizeof(USva));
	}

	/********************************************************/
	bool checkInfo( const dm::uint8& lenOfObj )const;
	dm::uint32 getInfoAddr( const dm::uint8& lenOfObj,const int& obj=0 )const;
	const dm::uint8* getInfo( const dm::uint8& lenOfObj,const int& obj )const;

	void makeInfo( const dm::uint8& lenOfObj,const bool& group,const dm::uint8& elemCount );
	void setInfoAddr( const dm::uint8& lenOfObj,const dm::uint32& objAddr,const int& obj=0 );
	dm::uint8* getInfo( const dm::uint8& lenOfObj,const int& obj );

	template<typename T>
	inline const T* getInfo(const int& obj )const{
		return (const T*)getInfo( sizeof(T),obj);
	}

	template<typename T>
	inline T* getInfo(const int& obj ){
		return (T*)getInfo( sizeof(T),obj);
	}

	template<typename T>
	inline void makeInfo( const bool& group,const dm::uint8& elemCount ){
		makeInfo(sizeof(T),group,elemCount);
	}

	template<typename T>
	inline void setInfoAddr( const dm::uint32& objAddr,const int& obj=0 ){
		setInfoAddr(sizeof(T),objAddr,obj);
	}
protected:
	dm::uint32 getObjAddress( const dm::uint8* buf )const;
	void setObjAddress( dm::uint32 address, dm::uint8* buf )const;

private:
	dm::uint8* m_data;	// ldu的缓冲区
	dm::uint8  m_size;	// ldu的缓冲区大小
	dm::uint8  m_len;		// 当前apdu有效长度

	dm::uint8 m_commonLen;	// 公共数据长度

	//////////////////////  系统参数

	// 公共地址长度 1或2
	dm::uint8 m_LenOfCommonAddr;

	// 传送原因长度 1或2
	dm::uint8 m_LenOfCause;

	// 信息对象地址长度 1，2，3
	dm::uint8 m_LenOfObjAddr;

	// APDU最大长度
	dm::uint16 m_maxLenOfApdu;
};

}
}

#endif /* INCLUDE_DM_FRAME_FRAME104APDU_HPP_ */
